package cn.iocoder.yudao.module.call.mq.consumer.product;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.call.controller.admin.task.vo.CallTaskControlReqVO;
import cn.iocoder.yudao.module.call.controller.admin.task.vo.CallTaskPageReqVO;
import cn.iocoder.yudao.module.call.dal.dataobject.task.CallTaskDO;
import cn.iocoder.yudao.module.call.enums.CallTaskStatusEnum;
import cn.iocoder.yudao.module.call.enums.CallTypeEnum;
import cn.iocoder.yudao.module.call.enums.CmTaskTypeEnum;
import cn.iocoder.yudao.module.call.service.task.CallTaskService;
import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
import cn.iocoder.yudao.module.system.enums.product.ProductEnum;
import cn.iocoder.yudao.module.system.mq.message.product.ProductExpireMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

/**
 * 针对 {@link ProductExpireMessage} 的消费者
 *
 * @author PetePower
 */
@Component
@Slf4j
public class CallProductExpireConsumer {
    @Resource
    private TenantApi tenantApi;

    @Resource
    private CallTaskService callTaskService;

    @EventListener
    @Async // Spring Event 默认在 Producer 发送的线程，通过 @Async 实现异步
    public void onMessage(ProductExpireMessage message) {
        log.info("ProductExpire:{}", message);
        if (message.getCode().equals(ProductEnum.IVR_NUM.getCode())) {
            //并发数过期
            TenantUtils.execute(message.getTenantId(), () -> {
                Integer IvrNumTotal = tenantApi.getTotalNumByCode(ProductEnum.IVR_NUM.getCode());
                CallTaskPageReqVO callTaskPageReqVO = new CallTaskPageReqVO();
                callTaskPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
                callTaskPageReqVO.setStatus(CallTaskStatusEnum.RUNNING.getStatus());
                callTaskPageReqVO.setType(CmTaskTypeEnum.TO_IVR.getType());
                List<CallTaskDO> taskDOList = callTaskService.getTaskPage(callTaskPageReqVO).getList();
                if (ObjectUtil.isEmpty(IvrNumTotal) || IvrNumTotal <= 0) {
                    //为0时直接全部停止
                    taskDOList.forEach(item -> {
                        callTaskService.controlTask(new CallTaskControlReqVO().setAction("stop").setId(item.getId()).setRestoreIvrNum(false));
                    });
                } else {
                    //还有剩余 从最早的任务开始停止,直到剩余并发数足够
                    int runningNum = taskDOList.stream().mapToInt(CallTaskDO::getMaxNum).sum();
                    log.info("expire-log IvrNumTotal: {} runningNum:{}", IvrNumTotal, runningNum);
                    //为保持缓存中的计数不出问题 将缓存还原再重新扣减一次
                    tenantApi.updateTenantProductBalance(ProductEnum.IVR_NUM.getCode(), message.getTenantId(), true, runningNum);
                    for (CallTaskDO item : taskDOList) {
                        if (IvrNumTotal.compareTo(runningNum) < 0) {
                            //如果企业的并发数量 小于正再被占用的数量,就停止一个
                            callTaskService.controlTask(new CallTaskControlReqVO().setAction("stop").setId(item.getId()).setRestoreIvrNum(false));
                            runningNum = runningNum - item.getMaxNum();
                        } else {
                            break;
                        }
                    }
                    //重新扣除返还后还在运行的并发数
                    tenantApi.updateTenantProductBalance(ProductEnum.IVR_NUM.getCode(), message.getTenantId(), false, runningNum);
                }
            });
        }
    }

}
